#include "syntax_parser.h"
#include "errors_warnings.h"


#include "main_container.h"
extern MainContainer * CompilerData;


// <model_body> ~ <using_directives> <model_define> <model_structure>  {using, define, NAME, generate, terminate, advance, enter, leave, seize, release, inqueue, outqueue, arrive, depart, model, goto, if, wait, join, create, split, gather, execute, exec, }}
void Parser::Parse_ModelBody(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ModelBody");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if( (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordUsing)		||	/* currentUnit == using		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDefine)		||	/* currentUnit == define	*/
		(currentUnit.type == LUTypeIdentifier)											||	/* currentUnit == NAME		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGenerate)	||	/* currentUnit == generate	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTerminate)	||	/* currentUnit == terminate	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAdvance)	||	/* currentUnit == advance	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordEnter)		||	/* currentUnit == enter		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordLeave)		||	/* currentUnit == leave		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSeize)		||	/* currentUnit == seize		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRelease)	||	/* currentUnit == release	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordInqueue)	||	/* currentUnit == inqueue	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOutqueue)	||	/* currentUnit == outqueue	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordArrive)		||	/* currentUnit == arrive	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDepart)		||	/* currentUnit == depart	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordModel)		||	/* currentUnit == model		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGoto)		||	/* currentUnit == goto		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf)			||	/* currentUnit == if		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWait)		||	/* currentUnit == wait		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordJoin)		||	/* currentUnit == join		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCreate)		||	/* currentUnit == create	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSplit)		||	/* currentUnit == split		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGather)		||	/* currentUnit == gather	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExecute)	||	/* currentUnit == execute	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExec)		||	/* currentUnit == exec		*/
		(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace) )	/* currentUnit == } */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized one of lexic units or keywords: \"using\", \"define\", NAME, \"generate\", \"terminate\", \"advance\", \"enter\", \"leave\", \"seize\", \"release\", \"inqueue\", \"outqueue\", \"arrive\", \"depart\", \"model\", \"goto\", \"if\", \"wait\", \"join\", \"create\", \"split\", \"gather\", \"execute\", \"exec\", }.");
#endif
		// write type of production in this node
		parent->Production = Gr_ModelBody__UsingDirectives_ModelDefine_ModelStructure;

		// process nonterminal symbol <using_directives> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_UsingDirectives(newNode0);

		// process nonterminal symbol <model_define> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_ModelDefine(newNode1);

		// process nonterminal symbol <model_structure> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_ModelStructure(newNode2);
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_BODY_BEGINNING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ModelBody");
#endif
}

// <model_define> ~ define { <define_body_statements> }  {define}
// <model_define> ~ ? {NAME, generate, terminate, advance, enter, leave, seize, release, inqueue, outqueue, arrive, depart, model, goto, if, wait, join, create, split, gather, execute, exec, }}
void Parser::Parse_ModelDefine(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ModelDefine");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDefine)		/* currentUnit == define */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"define\".");
#endif
		// write type of production in this node
		parent->Production =Gr_ModelDefine__define_spLCBrac_DefineBodyStatements_spRCBrac;

		// process terminal symbol 'define' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)	/* currentUnit == { */
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterLeftCurlyBrace.");
#endif
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <define_body_statements> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_DefineBodyStatements(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)	/* currentUnit == } */
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightCurlyBrace.");
#endif
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else if((currentUnit.type == LUTypeIdentifier)										||	/* currentUnit == NAME		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGenerate)	||	/* currentUnit == generate	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTerminate)	||	/* currentUnit == terminate	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAdvance)	||	/* currentUnit == advance	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordEnter)		||	/* currentUnit == enter		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordLeave)		||	/* currentUnit == leave		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSeize)		||	/* currentUnit == seize		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRelease)	||	/* currentUnit == release	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordInqueue)	||	/* currentUnit == inqueue	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOutqueue)	||	/* currentUnit == outqueue	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordArrive)		||	/* currentUnit == arrive	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDepart)		||	/* currentUnit == depart	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordModel)		||	/* currentUnit == model		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGoto)		||	/* currentUnit == goto		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf)			||	/* currentUnit == if		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWait)		||	/* currentUnit == wait		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordJoin)		||	/* currentUnit == join		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCreate)		||	/* currentUnit == create	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSplit)		||	/* currentUnit == split		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGather)		||	/* currentUnit == gather	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExecute)	||	/* currentUnit == execute	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExec)		||	/* currentUnit == exec		*/
		(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace))		/* currentUnit == }	*/
	{
		// write type of production in this node
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized one of lexic units or keywords: NAME, \"generate\", \"terminate\", \"advance\", \"enter\", \"leave\", \"seize\", \"release\", \"inqueue\", \"outqueue\", \"arrive\", \"depart\", \"model\", \"goto\", \"if\", \"wait\", \"join\", \"create\", \"split\", \"gather\", \"execute\", \"exec\", }.");
#endif
		parent->Production = Gr_ModelDefine__epsilon;
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_DEFINE_BEGINNING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ModelDefine");
#endif
}

// <label_gpss_block> ~ <block_labels> <gpss_block>  {NAME, generate, terminate, advance, enter, leave, seize, release, inqueue, outqueue, arrive, depart, model, goto, if, wait, join, create, split, gather, execute, exec}
void Parser::Parse_LabelGpssBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_LabelGpssBlock");
#endif
	LexicUnit currentUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	if( (currentUnit.type == LUTypeIdentifier)											||	/* currentUnit == NAME		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGenerate)	||	/* currentUnit == generate	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTerminate)	||	/* currentUnit == terminate	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAdvance)	||	/* currentUnit == advance	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordEnter)		||	/* currentUnit == enter		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordLeave)		||	/* currentUnit == leave		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSeize)		||	/* currentUnit == seize		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRelease)	||	/* currentUnit == release	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordInqueue)	||	/* currentUnit == inqueue	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOutqueue)	||	/* currentUnit == outqueue	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordArrive)		||	/* currentUnit == arrive	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDepart)		||	/* currentUnit == depart	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordModel)		||	/* currentUnit == model		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGoto)		||	/* currentUnit == goto		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf)			||	/* currentUnit == if		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWait)		||	/* currentUnit == wait		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordJoin)		||	/* currentUnit == join		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCreate)		||	/* currentUnit == create	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSplit)		||	/* currentUnit == split		*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGather)		||	/* currentUnit == gather	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExecute)	||	/* currentUnit == execute	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExec) )			/* currentUnit == exec		*/
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized one of lexic units or keywords: NAME, \"generate\", \"terminate\", \"advance\", \"enter\", \"leave\", \"seize\", \"release\", \"inqueue\", \"outqueue\", \"arrive\", \"depart\", \"model\", \"goto\", \"if\", \"wait\", \"join\", \"create\", \"split\", \"gather\", \"execute\", \"exec\".");
#endif

		// write type of production in this node
		parent->Production = Gr_LabelGpssBlock__BlockLabels_GpssBlock;

		// process nonterminal symbol <block_labels> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_BlockLabels(newNode0);

		// process nonterminal symbol <gpss_block> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_GpssBlock(newNode1);

	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LABEL_GPSS_BLOCK_BEGINNING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_LabelGpssBlock");
#endif
}




// <model_structure> ~ <label_gpss_block> <model_structure>  {NAME, generate, terminate, advance, enter, leave, seize, release, inqueue, outqueue, arrive, depart, model, goto, if, wait, join, create, split, gather, execute, exec}
// <model_structure> ~ ? {}}
void Parser::Parse_ModelStructure(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ModelStructure");
#endif
	LexicUnit currentUnit;

	while(1)
	{
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif

		if( (currentUnit.type == LUTypeIdentifier)											||	/* currentUnit == NAME		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGenerate)	||	/* currentUnit == generate	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTerminate)	||	/* currentUnit == terminate	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAdvance)	||	/* currentUnit == advance	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordEnter)		||	/* currentUnit == enter		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordLeave)		||	/* currentUnit == leave		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSeize)		||	/* currentUnit == seize		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRelease)	||	/* currentUnit == release	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordInqueue)	||	/* currentUnit == inqueue	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOutqueue)	||	/* currentUnit == outqueue	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordArrive)		||	/* currentUnit == arrive	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDepart)		||	/* currentUnit == depart	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordModel)		||	/* currentUnit == model		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGoto)		||	/* currentUnit == goto		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf)			||	/* currentUnit == if		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWait)		||	/* currentUnit == wait		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordJoin)		||	/* currentUnit == join		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCreate)		||	/* currentUnit == create	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSplit)		||	/* currentUnit == split		*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGather)		||	/* currentUnit == gather	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExecute)	||	/* currentUnit == execute	*/
			(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExec) )			/* currentUnit == exec		*/
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized one of lexic units or keywords: NAME, \"generate\", \"terminate\", \"advance\", \"enter\", \"leave\", \"seize\", \"release\", \"inqueue\", \"outqueue\", \"arrive\", \"depart\", \"model\", \"goto\", \"if\", \"wait\", \"join\", \"create\", \"split\", \"gather\", \"execute\", \"exec\".");
#endif
			// write type of production in this node
			parent->Production = Gr_ModelStructure__LabelGpssBlock_ModelStructure;

			// process nonterminal symbol <label_gpss_block> 
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_LabelGpssBlock(newNode0);

		}
		else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)	/* currentUnit == }	*/
		{
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Recognized SpecialCharacterRightCurlyBrace.");
#endif
			// write type of production in this node
			parent->Production = Gr_ModelStructure__LabelGpssBlock_ModelStructure;
			break;
		}
		else
		{		
#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Error. Recovery is to skip this lexic unit.");
#endif
			// ERROR has been found
			// REPORT ERROR
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_MODEL_STRUCTURE_BEGINNING);
			// MAKE LOGICAL RECOVERING
			CurrentLexicPosition++;
			break;
		}
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ModelStructure");
#endif
}

// <gpss_block> ~ <generate_block>  {generate}
// <gpss_block> ~ <terminate_block>  {terminate}
// <gpss_block> ~ <advance_block>  {advance}
// <gpss_block> ~ <enter_block>  {enter}
// <gpss_block> ~ <leave_block>  {leave}
// <gpss_block> ~ <seize_block>  {seize}
// <gpss_block> ~ <release_block>  {release}
// <gpss_block> ~ <inqueue_block>  {inqueue}
// <gpss_block> ~ <outqueue_block>  {outqueue}
// <gpss_block> ~ <arrive_block>  {arrive}
// <gpss_block> ~ <depart_block>  {depart}
// <gpss_block> ~ <model_instance_block>  {model, NAME}
// <gpss_block> ~ <goto_block>  {goto}
// <gpss_block> ~ <if_block>  {if}
// <gpss_block> ~ <wait_block>  {wait}
// <gpss_block> ~ <join_group_block>  {join}
// <gpss_block> ~ <leave_group_block>  {leave}
// <gpss_block> ~ <create_block>  {create}
// <gpss_block> ~ <split_block>  {split}
// <gpss_block> ~ <gather_block>  {gather}
// <gpss_block> ~ <execute_block>  {execute, exec}
void Parser::Parse_GpssBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_GpssBlock");
#endif
	LexicUnit currentUnit;
	LexicUnit nextUnit;
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	nextUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition+1);

	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGenerate)			/* currentUnit == generate */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"generate\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__GenerateBlock;

		// process nonterminal symbol <generate_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_GenerateBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordTerminate)	/* currentUnit == terminate */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"terminate\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__TerminateBlock;

		// process nonterminal symbol <terminate_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_TerminateBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAdvance)		/* currentUnit == advance */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"advance\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__AdvanceBlock;

		// process nonterminal symbol <advance_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_AdvanceBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordEnter)		/* currentUnit == enter */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"enter\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__EnterBlock;

		// process nonterminal symbol <enter_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_EnterBlock(newNode0);
	}
	else if((currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordLeave) && 
		(nextUnit.type == LUTypeKeyword && nextUnit.subtype == KeywordGroupLower))		/* currentUnit == leave */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"leave\".");
#endif
		
		// write type of production in this node
		parent->Production = Gr_GpssBlock__LeaveGroupBlock;

		// process nonterminal symbol <leave_group_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_LeaveGroupBlock(newNode0);
		

	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordLeave)
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"leave\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__LeaveBlock;

		// process nonterminal symbol <leave_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_LeaveBlock(newNode0);

	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSeize)		/* currentUnit == seize */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"seize\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__SeizeBlock;

		// process nonterminal symbol <seize_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SeizeBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRelease)		/* currentUnit == release */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"release\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__ReleaseBlock;

		// process nonterminal symbol <release_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ReleaseBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordInqueue)		/* currentUnit == inqueue */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"inqueue\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__InqueueBlock;

		// process nonterminal symbol <inqueue_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_InqueueBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordOutqueue)	/* currentUnit == outqueue */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"outqueue\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__OutqueueBlock;

		// process nonterminal symbol <outqueue_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_OutqueueBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordArrive)		/* currentUnit == arrive */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"arrive\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__ArriveBlock;

		// process nonterminal symbol <arrive_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ArriveBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDepart)		/* currentUnit == depart */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"depart\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__DepartBlock;

		// process nonterminal symbol <depart_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_DepartBlock(newNode0);
	}
	else if( (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordModel) ||	/* currentUnit == model */
		(currentUnit.type == LUTypeIdentifier) )										/* currentUnit == NAME	*/
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"model\" or lexic unit NAME.");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__ModelInstanceBlock;

		// process nonterminal symbol <model_instance_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ModelInstanceBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGoto)		/* currentUnit == goto */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"goto\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__GotoBlock;

		// process nonterminal symbol <goto_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_GotoBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordIf)			/* currentUnit == if */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"if\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__IfBlock;

		// process nonterminal symbol <if_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_IfBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordWait)		/* currentUnit == wait */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"wait\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__WaitBlock;

		// process nonterminal symbol <wait_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_WaitBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordJoin)		/* currentUnit == join */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"join\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__JoinGroupBlock;

		// process nonterminal symbol <join_group_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_JoinGroupBlock(newNode0);
	}
	
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordCreate)		/* currentUnit == create */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"create\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__CreateBlock;

		// process nonterminal symbol <create_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_CreateBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSplit)		/* currentUnit == split */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"split\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__SplitBlock;

		// process nonterminal symbol <split_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SplitBlock(newNode0);
	}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordGather)		/* currentUnit == gather */
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keyword \"gather\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__GatherBlock;

		// process nonterminal symbol <gather_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_GatherBlock(newNode0);
	}
	else if((currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExecute) ||	/* currentUnit == execute	*/
		(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExec))		/* currentUnit == exec		*/
	{
#ifdef TRACE
		CompilerData->LogTrace->ReportLine("Recognized keywords \"execute\" or \"exec\".");
#endif
		// write type of production in this node
		parent->Production = Gr_GpssBlock__ExecuteBlock;

		// process nonterminal symbol <execute_block> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_ExecuteBlock(newNode0);
	}
	else
	{
		// ERROR has been found
		// REPORT ERROR
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_GPSS_BLOCK_BEGINNING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_GpssBlock");
#endif
}

//void Parser::Parse_DefineBodyStatements(SyntaxTreeNode * parent)
//{
//}


